# -*- coding: utf-8 -*-

from sqlalchemy.orm import mapped_column, Mapped, relationship
from sqlalchemy import Column, String, Integer, Boolean, BigInteger, Date, DateTime, ForeignKey, func
from typing_extensions import Annotated
import datetime
from decimal import Decimal
from typing import Optional, List
from database import SqlBase
from sqlalchemy.orm import class_mapper

# 提取共用部分
int_pk = Annotated[int, mapped_column(primary_key=True)]
int_pk_auto = Annotated[int, mapped_column(primary_key=True, autoincrement=True)]
timestamp_default_now = Annotated[
    datetime.datetime,
    mapped_column(nullable=True, server_default=func.now())
]
timestamp_not_null = Annotated[
    datetime.datetime,
    mapped_column(nullable=False),
]
required_unique_name = Annotated[str, mapped_column(String(100), unique=True, nullable=False)]
required_string = Annotated[str, mapped_column(String(64), nullable=False)]

str_30 = Annotated[str, 30]
str_50 = Annotated[str, 50]
num_12_4 = Annotated[Decimal, 12]
num_6_2 = Annotated[Decimal, 6]


class YgBase(SqlBase):
    __abstract__ = True
    del_flag: Mapped[bool] = mapped_column(default=False, nullable=True)
    create_by: Mapped[str] = mapped_column(String(32), nullable=False)
    create_time: Mapped[timestamp_default_now]
    update_by: Mapped[str] = mapped_column(String(32), nullable=False)
    update_time: Mapped[timestamp_default_now]


def add_serializer(cls):
    def to_dict(self):
        # 有懒加载问题, 需手动getattr 或 print,log函数去触发加载;
        dic = self.__dict__
        # 以下是坑点
        if "_sa_instance_state" in dic:
            del dic["_sa_instance_state"]

        def has_func(obj, f):
            return hasattr(obj, f) and callable(getattr(obj, f))

        def data_format(obj):
            if isinstance(obj, datetime.datetime):
                return obj.strftime("%Y-%m-%d %H:%M:%S")
            if hasattr(obj, 'to_dict'):
                return obj.to_dict()
            if isinstance(obj, list):
                return [data_format(item) for item in obj]
            else:
                return obj

        # return {key: data_format(value) for key, value in dic.items()}
        # return dict((key, data_format(getattr(self, key))) for key in dic)
        return dict((key, data_format(value)) for key, value in dic.items())

    def asDict(self):
        """自动生成的to_json方法"""

        # orm对象getattr 和 print 都能触发加载; 缺点不包括子对象
        def date_format(obj):
            if isinstance(obj, datetime.datetime):
                return obj.strftime("%Y-%m-%d %H:%M:%S")
            else:
                return obj

        return dict((col.name, date_format(getattr(self, col.name))) for col in class_mapper(self.__class__).mapped_table.c)

    setattr(cls, 'to_dict', to_dict)
    setattr(cls, 'asDict', asDict)
    return cls
